<!doctype html>
<html>
<head>
  <meta charset='utf-8'>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width">
  <title>Cycle.js - API reference (dom)</title>

  <!-- Flatdoc -->
  <script src='../support/vendor/jquery.js'></script>
  <script src='../support/vendor/highlight.pack.js'></script>
  <script src='../legacy.js'></script>
  <script src='../flatdoc.js'></script>

  <!-- Others -->
  <script async src="//static.jsbin.com/js/embed.js"></script>

  <!-- Flatdoc theme -->
  <link href='../theme/style.css' rel='stylesheet'>
  <script src='../theme/script.js'></script>
  <link href='../support/vendor/highlight-github-gist.css' rel='stylesheet'>

  <!-- Meta -->
  <meta content="Cycle.js - API reference (dom)" property="og:title">
  <meta content="A functional and reactive JavaScript framework for predictable code" name="description">

  <!-- Content -->
  <script id="markdown" type="text/markdown" src="index.html">
# Cycle DOM

A collection of Cycle.js drivers to enable interaction with the DOM. It includes a DOM Driver, an HTML Driver, both based on [snabbdom](https://github.com/paldepind/snabbdom/) as the Virtual DOM library.

```
npm install @cycle/dom
```

## Browser support

These are the browsers we officially support currently. Cycle.js may not work (or work partially) in other browsers.

[![Sauce Test Status](https://saucelabs.com/browser-matrix/cyclejs-dom.svg)](https://saucelabs.com/u/cyclejs-dom)

# Isolation semantics

Cycle DOM supports isolation between components using the `@cycle/isolate` package. Here is how isolation contexts work in Cycle DOM given a `scope` to `isolate(Component, scope)`:

**When the scope is the `':root'` string: no isolation.**

The child component will have run in the same context as its parent, and methods like `DOMSource.select()` will inspect the DOM trees of the parent. This means the child component is able to inspect DOM trees that it did not itself produce.

**When the scope is a selector string (e.g. '.foo' or '#foo'): siblings isolation.**

A `DOMSource.select()` call in a parent component will have access to the DOM trees in both children isolated with "siblings isolation" (which means there is no parent-child isolation). However, a `DOMSource.select()` inside a child component isolated with "siblings isolation" will have no access to the DOM trees in other children components isolated with "siblings isolation".

**When the scope is any other string: total isolation.**

A `DOMSource.select()` call in a parent component will have no access to the DOM trees in a totally isolated child. Also, sibling components will have no access to the DOM trees in a totally isolated sibling component.

# API


## <a id="makeDOMDriver"></a> `makeDOMDriver(container, options)`

A factory for the DOM driver function.

Takes a `container` to define the target on the existing DOM which this
driver will operate on, and an `options` object as the second argument. The
input to this driver is a stream of virtual DOM objects, or in other words,
Snabbdom "VNode" objects. The output of this driver is a "DOMSource": a
collection of Observables queried with the methods `select()` and `events()`.

`DOMSource.select(selector)` returns a new DOMSource with scope restricted to
the element(s) that matches the CSS `selector` given.

`DOMSource.events(eventType, options)` returns a stream of events of
`eventType` happening on the elements that match the current DOMSource. The
event object contains the `ownerTarget` property that behaves exactly like
`currentTarget`. The reason for this is that some browsers doesn't allow
`currentTarget` property to be mutated, hence a new property is created. The
returned stream is an *xstream* Stream if you use `@cycle/xstream-run` to run
your app with this driver, or it is an RxJS Observable if you use
`@cycle/rxjs-run`, and so forth. The `options` parameter can have the
property `useCapture`, which is by default `false`, except it is `true` for
event types that do not bubble. Read more here
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
about the `useCapture` and its purpose.

`DOMSource.elements()` returns a stream of the DOM element(s) matched by the
selectors in the DOMSource. Also, `DOMSource.select(':root').elements()`
returns a stream of DOM element corresponding to the root (or container) of
the app on the DOM.

#### Arguments:

- `container: String|HTMLElement` the DOM selector for the element (or the element itself) to contain the rendering of the VTrees.
- `options: DOMDriverOptions` an object with two optional properties: 
  - `modules: array` overrides `@cycle/dom`'s default Snabbdom modules as
    as defined in [`src/modules.ts`](./src/modules.ts).
  - `transposition: boolean` enables/disables transposition of inner streams
    in the virtual DOM tree.

#### Returns:

*(Function)* the DOM driver function. The function expects a stream of VNode as input, and outputs the DOMSource object.

## <a id="makeHTMLDriver"></a> `makeHTMLDriver(effect, options)`

A factory for the HTML driver function.

Takes an `effect` callback function and an `options` object as arguments. The
input to this driver is a stream of virtual DOM objects, or in other words,
Snabbdom "VNode" objects. The output of this driver is a "DOMSource": a
collection of Observables queried with the methods `select()` and `events()`.

The HTML Driver is supplementary to the DOM Driver. Instead of producing
elements on the DOM, it generates HTML as strings and does a side effect on
those HTML strings. That side effect is described by the `effect` callback
function. So, if you want to use the HTML Driver on the server-side to render
your application as HTML and send as a response (which is the typical use
case for the HTML Driver), you need to pass something like the
`html => response.send(html)` function as the `effect` argument. This way,
the driver knows what side effect to cause based on the HTML string it just
rendered.

The HTML driver is useful only for that side effect in the `effect` callback.
It can be considered a sink-only driver. However, in order to serve as a
transparent replacement to the DOM Driver when rendering from the server, the
HTML driver returns a source object that behaves just like the DOMSource.
This helps reuse the same application that is written for the DOM Driver.
This fake DOMSource returns empty streams when you query it, because there
are no user events on the server.

`DOMSource.select(selector)` returns a new DOMSource with scope restricted to
the element(s) that matches the CSS `selector` given.

`DOMSource.events(eventType, options)` returns an empty stream. The returned
stream is an *xstream* Stream if you use `@cycle/xstream-run` to run your app
with this driver, or it is an RxJS Observable if you use `@cycle/rxjs-run`,
and so forth.

`DOMSource.elements()` returns the stream of HTML string rendered from your
sink virtual DOM stream.

#### Arguments:

- `effect: Function` a callback function that takes a string of rendered HTML as input and should run a side effect, returning nothing.
- `options: HTMLDriverOptions` an object with one optional property: `transposition: boolean` enables/disables transposition of inner streams in
the virtual DOM tree.

#### Returns:

*(Function)* the HTML driver function. The function expects a stream of VNode as input, and outputs the DOMSource object.

## <a id="mockDOMSource"></a> `mockDOMSource(mockConfig)`

A factory function to create mocked DOMSource objects, for testing purposes.

Takes a `streamAdapter` and a `mockConfig` object as arguments, and returns
a DOMSource that can be given to any Cycle.js app that expects a DOMSource in
the sources, for testing.

The `streamAdapter` parameter is a package such as `@cycle/xstream-adapter`,
`@cycle/rxjs-adapter`, etc. Import it as `import a from '@cycle/rx-adapter`,
then provide it to `mockDOMSource. This is important so the DOMSource created
knows which stream library should it use to export its streams when you call
`DOMSource.events()` for instance.

The `mockConfig` parameter is an object specifying selectors, eventTypes and
their streams. Example:

```js
const domSource = mockDOMSource(RxAdapter, {
  '.foo': {
    'click': Rx.Observable.of({target: {}}),
    'mouseover': Rx.Observable.of({target: {}}),
  },
  '.bar': {
    'scroll': Rx.Observable.of({target: {}}),
    elements: Rx.Observable.of({tagName: 'div'}),
  }
});

// Usage
const click$ = domSource.select('.foo').events('click');
const element$ = domSource.select('.bar').elements();
```

The mocked DOM Source supports isolation. It has the functions `isolateSink`
and `isolateSource` attached to it, and performs simple isolation using
classNames. *isolateSink* with scope `foo` will append the class `___foo` to
the stream of virtual DOM nodes, and *isolateSource* with scope `foo` will
perform a conventional `mockedDOMSource.select('.__foo')` call.

#### Arguments:

- `mockConfig: Object` an object where keys are selector strings and values are objects. Those nested objects have `eventType` strings as keys
and values are streams you created.

#### Returns:

*(Object)* fake DOM source object, with an API containing `select()` and `events()` and `elements()` which can be used just like the DOM Driver's
DOMSource.

## <a id="h"></a> `h()`

The hyperscript function `h()` is a function to create virtual DOM objects,
also known as VNodes. Call

```js
h('div.myClass', {style: {color: 'red'}}, [])
```

to create a VNode that represents a `DIV` element with className `myClass`,
styled with red color, and no children because the `[]` array was passed. The
API is `h(tagOrSelector, optionalData, optionalChildrenOrText)`.

However, usually you should use "hyperscript helpers", which are shortcut
functions based on hyperscript. There is one hyperscript helper function for
each DOM tagName, such as `h1()`, `h2()`, `div()`, `span()`, `label()`,
`input()`. For instance, the previous example could have been written
as:

```js
div('.myClass', {style: {color: 'red'}}, [])
```

There are also SVG helper functions, which apply the appropriate SVG
namespace to the resulting elements. `svg()` function creates the top-most
SVG element, and `svg.g`, `svg.polygon`, `svg.circle`, `svg.path` are for
SVG-specific child elements. Example:

```js
svg({width: 150, height: 150}, [
  svg.polygon({
    attrs: {
      class: 'triangle',
      points: '20 0 20 150 150 20'
    }
  })
])
```


  </script>

  <!-- Initializer -->
  <script>
    Flatdoc.run({
      fetcher: function(callback) {
        callback(null, document.getElementById('markdown').innerHTML);
      },
      highlight: function (code, value) {
        return hljs.highlight(value, code).value;
      },
    });
  </script>

</head>
<body role='flatdoc' class="no-literate">



  <div class='header'>
    <div class='left'>
      <h1><a href="/"><img class="logo" src="../img/cyclejs_logo.svg" >Cycle.js</a></h1>
      <ul>
        <li><a href='../getting-started.html'>Documentation</a></li>
        <li><a href='../api/index.html'>API reference</a></li>
        <li><a href='../releases.html'>Releases</a></li>
      </ul>
    </div>
    <div class='right'>
      <!-- GitHub buttons: see https://ghbtns.com -->
      <iframe src="https://ghbtns.com/github-btn.html?user=cyclejs&amp;repo=cyclejs&amp;type=watch&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
    </div>
  </div>

  <div class='content-root'>
    <div class='menubar'>
      <div class='menu section'>

        <div role='flatdoc-menu'></div>

      </div>
    </div>
    <div role='flatdoc-content' class='content'></div>

  </div>


  <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
    ga('create', 'UA-43862400-3', 'auto');
    ga('send', 'pageview');
  </script>
  <script>
    ((window.gitter = {}).chat = {}).options = {
      room: 'cyclejs/cyclejs'
    };
  </script>
  <script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
</body>
</html>
